const isProxy = Symbol("isProxy1");
export function WatchValueChange<T = any>(val: any, callback: (target: any, key: string|number, value: any) => void): T {
    let type = Object.prototype.toString.call(val);
    if(type == '[object Object]') {
        for(let key in val) {
            val[key] = WatchValueChange(val[key], callback);
        }
        return new Proxy(val, {
            get: (target, idx: string) => {
                if(<any>idx == isProxy) {
                    return true;
                }
                return target[idx];
            },
            set: (target, idx: number, value: any) => {
                if(value[isProxy] == true) {
                    target[idx] = value;
                } else {
                    target[idx] = WatchValueChange(value, callback);
                }
                callback(target, idx, value);
                return true;
            }
        });
    }
    if(type == '[object Array]') {
        for(let i = 0; i < val; i++) {
            try {
                if(val[i][isProxy] == false) {
                    val[i] = WatchValueChange(val[i], callback);
                }                    
            } catch (error) {

            }
        }
        return new Proxy(val, {
            get: (target, idx: string) => {
                if(<any>idx == isProxy) {
                    return true;
                }
                return target[idx];
            },
            set: (target, idx: number, value: any) => {
                if(value[isProxy] == true) {
                    target[idx] = value;
                } else {
                    target[idx] = WatchValueChange(value, callback);
                }
                if(<any>idx != 'length') {
                    callback(target, idx, value);
                }
                return true;
            }
        });
    }
    return val;
}
export function addAttribute(originObj: any, val: {[key: string]: any}) {
    if(originObj == null || originObj == undefined) {
        return val;
    } else {
        return Object.assign(originObj, val);
    }
}